﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace ADSync
{
	class Program
	{
		static void Main(string[] args)
		{
			int exit = DoSync();
			Environment.Exit(exit);
		}


		static private int DoSync()
		{
			int errors = 0;
			string year = AcYear.CurrentAsString();
			string errortxt = null;
			string log = null;

			using (var con = new SapienDataClassesDataContext())
			{
				var memberships = con.VADMemberships
					.Where(en => en.groupname.EndsWith(year) && en.groupname.Length > 4)
					.Select(en => new Membership(en.groupname.ToUpper(), en.username.ToLower()));

				// workaround for Linq shortcoming, group this by reference code in the app-layer
				IGrouping<string, string>[] g = memberships
					.AsEnumerable()
					.GroupBy(m => m.Group, m => m.User)
					.ToArray();

				string[] existinggroups = con.ADGroups
					.Select(ex => ex.groupref)
					.ToArray();

				using (GroupManager groups = new GroupManager(g, true))
				{
					LogAction(con, "AD Sync started", "");
					groups.PopulateManagedGroupList(existinggroups);

					int count = groups.RemoveUnneededGroupMembers();
					LogAction(con, "Unneeded memships", count.ToString());

					// add groups that do not exit in AD
					string[] newgroups = groups.AddNewGroups();
					LogAction(con, "New groups", newgroups.Length.ToString());

					// add these all 'groups' to history list in db (managed groups)
					DateTime now = DateTime.Now;
					foreach (string newg in newgroups)
					{
						ADGroups adg = new ADGroups();
						adg.groupref = newg;
						adg.whencreated = now;
						con.ADGroups.InsertOnSubmit(adg);
					}
					con.SubmitChanges();

					// add all memberships in 'groups' - existing will not cause errors
					count = groups.AddGroupMemberships();
					LogAction(con, "Memships added", count.ToString());

					errors = groups.Log.Count;
					errortxt = groups.GetLogText(true);
					log = groups.GetLogText(false);
				}

				LogAction(con, "Errors", errors.ToString());
			}

			using (TextWriter t = new StreamWriter("c:\\SyncLog.txt"))
			{
				t.WriteLine("Run at: {0:g}, errors {1}", DateTime.Now, errors);
				t.WriteLine();
				t.WriteLine("Errors:");
				t.Write(errortxt);
				t.WriteLine();
				t.WriteLine("Successful actions:");
				t.WriteLine();
				t.Write(log);
			}

			int exitcode = (errors == 0 ? 0 : 1);
			return exitcode;
		}

		static private void LogAction(SapienDataClassesDataContext con, string activity, string ident)
		{
			ActivityLog l = new ActivityLog();
			l.ip = "?";
			l.username = "AD sync tool";
			l.whenact = DateTime.Now;
			l.action = activity;
			l.details = ident;

			con.ActivityLog.InsertOnSubmit(l);
			con.SubmitChanges();
		}
	}
}
